﻿using System;
using System.IO;
using System.Threading;
using Limestone.Fields;
using Limestone.Storage.XML;
using NUnit.Framework;
using SharpTestsEx;

namespace Limestone.Test
{
    [TestFixture]
    public class XmlStoragePageFixture : TestBase
    {

        [Test]
        public void TemplateCreate()
        {
            var templateProvider = GetTemplateProvider();

            /* Index */
            var index = new PageTemplate { Name = "Index", HelpText = "", Path = "/Index" };
            var tfld = new TextFieldSetting("content") { HelpText = "", Title = "Content", EditMode = TextEditMode.Rich, Multiline = true };
            index.FieldSettings.Add(tfld);
            templateProvider.Save(index);

            var template = templateProvider.Get("/index");

            Assert.AreEqual(index.Name, template.Name);
        }
        [Test]
        public void PageCreate()
        {
            var pageProvider = GetPageProvider();

            /* Index */
            var index = new Page("A title") { Name = "Start", Path = "/" };
            pageProvider.Save(index);

            var page = pageProvider.Get("/");

            Assert.AreEqual(index.Name, page.Name);
        }

        [Test]
        public void PageStructureCreate()
        {
            var pageProvider = GetPageProvider();

            /* wicked path */
            var index = new Page("A title") { Name = "Start", Path = "/a/wicked/long/path/to/my/page" };
            pageProvider.Save(index);

            var page = pageProvider.Get("/a/wicked/long/path/to/my/page");

            Assert.AreEqual(index.Name, page.Name);
        }

        [Test]
        public void ChildTest()
        {
            var pageProvider = GetPageProvider();

            /* mom */
            var mom = new Page("A title") { Name = "mom", Path = "/mom" };
            pageProvider.Save(mom);

            var page = pageProvider.Get("/mom");

            Assert.AreEqual(mom.Name, page.Name);


            /* child */
            var child = new Page("A child title") { Name = "child", Path = "/mom/child" };
            pageProvider.Save(child);

            var childPage = pageProvider.Get("/mom/child");

            Assert.AreEqual(child.Name, childPage.Name);

            Assert.IsTrue(Directory.Exists(BasePagePath + @"\mom"));

            Assert.IsTrue(File.Exists(BasePagePath + @"\mom\" + GetXmlCfg().FolderIndexPageName + ".page"));

            Assert.IsFalse(File.Exists(BasePagePath + @"\mom.page"));

            // TODO kolla navigation

        }

        [Test]
        public void DeletePage()
        {
            var pageProvider = GetPageProvider();
            var pageStubCache = GetPageStubCache();

            /* mom */
            var goner = new Page("A title") { Name = "goner", Path = "/goner" };
            pageProvider.Save(goner);

            var page = pageProvider.Get("/goner");

            Assert.AreEqual(goner.Name, page.Name);

            pageProvider.Delete(goner);

            Assert.IsNull(pageProvider.Get("/goner"));
            Assert.IsFalse(File.Exists(BasePagePath + @"\goner.page"));
            Assert.IsTrue(File.Exists(BaseTrashcanPath + @"\goner.page"));
            Assert.IsNull(pageStubCache.GetPageStub("/goner"));
        }
        [Test]
        public void DeleteDirectory()
        {
            var pageProvider = GetPageProvider();
            var pageStubCache = GetPageStubCache();

            // directories
            pageProvider.Save(new Page("A title") { Name = "gonerParent", Path = "/gonerParent" });
            pageProvider.Save(new Page("A title") { Name = "goner", Path = "/gonerParent/goner" });
            pageProvider.Delete("/gonerParent");

            pageProvider.Get("/gonerParent").Should().Be.Null();
            File.Exists(BasePagePath + @"\gonerParent.page").Should().Be.False();
            pageStubCache.GetPageStub("/gonerParent").Should().Be.Null();
            File.Exists(BaseTrashcanPath + @"\gonerParent\goner.page").Should().Be.True();
        }

        [Test]
        public void DeleteMultipleTest()
        {
            var pageProvider = GetPageProvider();
            var pageStubCache = GetPageStubCache();

            // pages
            pageProvider.Save(new Page("A title") { Name = "goner", Path = "/goner" });
            pageProvider.Delete("/goner");

            pageProvider.Save(new Page("A title") { Name = "goner", Path = "/goner" });
            pageProvider.Delete("/goner");

            // directories
            pageProvider.Save(new Page("A title") { Name = "gonerParent", Path = "/gonerParent" });
            pageProvider.Save(new Page("A title") { Name = "goner", Path = "/gonerParent/goner" });
            pageProvider.Delete("/gonerParent");

            pageProvider.Save(new Page("A title") { Name = "gonerParent", Path = "/gonerParent" });
            pageProvider.Save(new Page("A title") { Name = "goner", Path = "/gonerParent/goner" });
            pageProvider.Delete("/gonerParent");

            pageProvider.Get("/goner").Should().Be.Null();
            File.Exists(BasePagePath + @"\goner.page").Should().Be.False();
            pageStubCache.GetPageStub("/goner").Should().Be.Null();
            File.Exists(BaseTrashcanPath + @"\goner.page").Should().Be.True();
            File.Exists(BaseTrashcanPath + @"\goner (1).page").Should().Be.True();

            pageProvider.Get("/gonerParent").Should().Be.Null();
            File.Exists(BasePagePath + @"\gonerParent.page").Should().Be.False();
            pageStubCache.GetPageStub("/gonerParent").Should().Be.Null();
            Directory.Exists(BaseTrashcanPath + @"\gonerParent").Should().Be.True();
            Directory.Exists(BaseTrashcanPath + @"\gonerParent (1)").Should().Be.True();
        }

        [Test]
        public void Testfilepathstuff()
        {
            var pageProvider = GetPageProvider();
            pageProvider.Save(new Page("A title") { Name = "goner", Path = "/goner" });
            var newFileName = GetUniqueDiscName(@"c:\temp\limestone\pages\goner.page");
            var newFolderName = GetUniqueDiscName(@"c:\temp\limestone\unique");
            var newFolderDoubleName = GetUniqueDiscName(@"c:\temp\limestone\pages");

            Assert.AreEqual("goner (1)", newFileName);
            Assert.AreEqual("unique", newFolderName);
            Assert.AreEqual("pages (1)", newFolderDoubleName);
        }

        private string GetUniqueDiscName(string desiredTargetPath, int attempt = 0)
        {
            var tryPath = desiredTargetPath;
            if (attempt > 0)
            {
                tryPath = Path.Combine(Path.GetDirectoryName(desiredTargetPath), Path.GetFileNameWithoutExtension(desiredTargetPath) + " (" + attempt + ").page");
            }
            if (File.Exists(tryPath) || Directory.Exists(tryPath))
            {
                return GetUniqueDiscName(desiredTargetPath, attempt + 1);
            }
            return Path.GetFileNameWithoutExtension(tryPath);
        }

        [Test]
        public void MoveToPageDuplicateShouldFail()
        {
            var pageProvider = GetPageProvider();
            var pageStubCache = GetPageStubCache();

            var source = pageProvider.Save(new Page("A title") { Name = "dupe", Path = "/dupe" });
            var targetParent = pageProvider.Save(new Page("A title") { Name = "targetParent", Path = "/targetParent" });
            var target = pageProvider.Save(new Page("A title") { Name = "dupe", Path = "/targetParent/dupe" });

            var moveResult = pageProvider.Move(source, targetParent.Path);

            moveResult.Should().Be.False();
            pageProvider.Get("/dupe").Should().Not.Be.Null();
            File.Exists(BasePagePath + @"\dupe.page").Should().Be.True();
            pageStubCache.GetPageStub("/dupe").Should().Not.Be.Null();
        }

        [Test]
        public void MoveToPage()
        {
            var pageProvider = GetPageProvider();
            var pageStubCache = GetPageStubCache();

            var source = pageProvider.Save(new Page("A title") { Name = "source", Path = "/source" });
            var target = pageProvider.Save(new Page("A title") { Name = "target", Path = "/target" });
            pageProvider.Move(source, target.Path);

            Assert.IsNull(pageProvider.Get("/source"));
            Assert.IsNotNull(pageProvider.Get("/target"));
            Assert.IsNotNull(pageProvider.Get("/target/source"));
            Assert.IsFalse(File.Exists(BasePagePath + @"\source.page"));
            Assert.IsNull(pageStubCache.GetPageStub("/source"));
            Assert.IsTrue(File.Exists(BasePagePath + @"\target\" + GetXmlCfg().FolderIndexPageName + ".page"));
        }

        [Test]
        public void LookupTinyFileCreation()
        {
            var pageProvider = GetPageProvider();


            /* start */
            var index = new Page("A title") { Name = "Start", Path = "/" };
            pageProvider.Save(index);

            var cache = GetPageStubCache();
            cache.LoadPageLookUpCache(true);

            Assert.IsNotNull(cache.GetPageStub("/"));
        }

        [Test]
        public void LookupFileCreation()
        {
            var pageProvider = GetPageProvider();


            /* start */
            var index = new Page("A title") { Name = "Start", Path = "/" };
            pageProvider.Save(index);

            /* simple */
            var simple = new Page("A title") { Name = "simple", Path = "/simple" };
            pageProvider.Save(simple);

            var cache = GetPageStubCache();
            cache.LoadPageLookUpCache(true);

            Assert.IsNotNull(cache.GetPageStub("/"));
            Assert.IsNotNull(cache.GetPageStub("/simple"));
        }

        [Test]
        public void LookupBigFileCreation()
        {
            var pageProvider = GetPageProvider();


            /* start */
            var index = new Page("A title") { Name = "Start", Path = "/" };
            pageProvider.Save(index);

            /* simple */
            var simple = new Page("A title") { Name = "simple", Path = "/simple" };
            pageProvider.Save(simple);

            /* mom */
            var mom = new Page("A title") { Name = "mom", Path = "/mom" };
            pageProvider.Save(mom);

            /* child */
            var child = new Page("A child title") { Name = "child", Path = "/mom/child" };
            pageProvider.Save(child);

            /* wicked path */
            var longPath = "/a/wicked/long/path/to/my/page";
            var longPathPage = new Page("A title") { Name = "Longie", Path = longPath };
            pageProvider.Save(longPathPage);

            var cache = GetPageStubCache();
            cache.LoadPageLookUpCache(true);

            cache.GetPageStub("/").Should().Not.Be.Null();
            //cache.GetPageStub("/a/wicked").Should().Not.Be.Null();
            //cache.GetPageStub("/simple").Should().Not.Be.Null();
            //cache.GetPageStub("/mom").Should().Not.Be.Null();
            //cache.GetPageStub("/mom/child").Should().Not.Be.Null();
            cache.GetPageStub(longPath).Should().Not.Be.Null();
        }
    }
}
